# -*- coding: utf-8 -*-

"""
 (c) 2023 - Copyright CTyunOS Inc

 Authors:
   youyifeng <youyf2@chinatelecom.cn>

"""
import logging
import os
from optparse import OptionParser

from cve_ease import OPENEULER_PRODUCT_REPO_MAP
from cve_ease import activate_session
from cve_ease.config import OSV_MAP
from cve_ease.helper import check_product
from cve_ease.helper import find_higest_srpm_version
from cve_ease.helper import one_instance_check, parseRPM, srpm_version_compare
from cve_ease.models import Repos, RPM, SRPM, PRODUCT

logger = logging.getLogger('cve-ease')


def get_usage_str(usage):
    return usage + "\n(Specify the --help global option for a list of other help options)"


def parser_repo(product_id):
    repos = Repos()
    for repo in OPENEULER_PRODUCT_REPO_MAP[product_id]:
        print("makecache %s" % repo)
        repos.addrepo(repo)
    return repos


def handle_repodata(gconfig, db_session, args):
    """[basic] Yum repodata tool"""
    # one instance
    lock = one_instance_check(gconfig.LOCK_FILE_PATH)
    if lock:
        raise Exception(f"Another cve-ease already running")

    usage = "usage: %prog repodata <options>"
    parser = OptionParser(usage=get_usage_str(usage))

    parser.add_option('-m', '--makecache', dest='makecache', action='store_true', default=False,
                      help='cache repodata to database')
    parser.add_option('-p', '--product', dest='product', default=None,
                      help='specific product (work with --check)')
    # OSV (Operating System Software Provider)
    parser.add_option('--osv', dest='osv', default=None,
                      help='specific osv rpm release')
    parser.add_option('-t', '--total', dest='total', action='store_true', default=False,
                      help='get total rpm statistics')
    parser.add_option('-l', '--list', dest='list', action='store_true', default=False,
                      help='list all rpm')
    parser.add_option('-c', '--check', dest='check', action='store_true', default=False,
                      help='check repo cve')
    parser.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False,
                      help='show verbose output')

    (options, args) = parser.parse_args(args)

    session = activate_session(db_session, gconfig)
    if gconfig.debug:
        print(" * active sql session")

    if options.makecache:
        productId = check_product(gconfig, options)
        print(" * Using product:", productId)

        repos = parser_repo(productId)
        allpkglist = repos.list()
        srpm_listdict = {}

        # recreate table
        RPM.__table__.drop(db_session.get_engine())
        RPM.__table__.create(db_session.get_engine())

        for index, (url, pkg) in enumerate(allpkglist):
            rpm = RPM()

            rpm.sourcerpm = pkg.sourcerpm
            rpm.sname, rpm.sver, rpm.srel, rpm.sepoch, rpm.sarch = parseRPM(rpm.sourcerpm)

            rpm.rpmname = pkg.rpmname
            rpm.name, rpm.ver, rpm.rel, rpm.epoch, rpm.arch = parseRPM(rpm.rpmname)

            rpm.location = pkg.location
            rpm.downloadurl = os.path.join(url, pkg.location)

            session.add(rpm)
            session.commit()

            if rpm.sname not in srpm_listdict:
                srpm_listdict[rpm.sname] = [rpm.sourcerpm]
            else:
                if rpm.sourcerpm not in srpm_listdict[rpm.sname]:
                    srpm_listdict[rpm.sname].append(rpm.sourcerpm)

            print("[%6d/%-6d] Cache OK! %s" % (index + 1, len(allpkglist) - index - 1, pkg.rpmname))
        # print(json.dumps(srpm_listdict, indent=4))
        print(" * organize cache, wait a moment...")

        # recreate table
        SRPM.__table__.drop(db_session.get_engine())
        SRPM.__table__.create(db_session.get_engine())

        for srpm in srpm_listdict:
            max_version = find_higest_srpm_version(srpm_listdict[srpm])
            srpm = SRPM()
            srpm.sourcerpm = max_version
            srpm.sname, srpm.sver, srpm.srel, srpm.sepoch, srpm.sarch = parseRPM(max_version)
            session.add(srpm)
            session.commit()
        print(" * cache SRPM table done!")
    elif options.list:
        rpmlist = session.query(RPM).all()
        if 0 == len(rpmlist):
            print(" WARNNING: no rpm cache found! you should run 'cve-ease repodata -m' to cache it.")
            return
        print(
            "%-45s %-20s %-5s  %-35s %-15s %s(%s)" % ("NAME", "VERSION", "EPOCH", "RELEASE", "ARCH", "SOURCE", "SNAME")
        )
        for pkg in rpmlist:
            rpmname = pkg.rpmname
            name, ver, rel, epoch, arch = parseRPM(rpmname)
            print("%-45s %-20s %-5s %-35s %-15s %s(%s)" % (
                name,
                ver,
                epoch or '0',
                rel,
                arch,
                pkg.sourcerpm,
                pkg.sname
            ))
    elif options.total:
        total = session.query(RPM).count()
        print("rpm total record :", total)
        if 0 == total:
            print(" WARNNING: no rpm cache found! you should run 'cve-ease repodata -m' to cache it.")
        total = session.query(SRPM).count()
        print("srpm total record :", total)
        if 0 == total:
            print(" WARNNING: no srpm cache found! you should run 'cve-ease repodata -m' to cache it.")
    elif options.check:
        productId = check_product(gconfig, options)
        print(" * Using product:", productId)
        if options.osv:
            print(" * Setup OSV :", options.osv)

        # SRPM store higest/uniq srpm info
        repodata_srpm = session.query(SRPM).all()
        from sqlalchemy import and_
        # PRODUCT is from cvrf info
        for srpm in repodata_srpm:
            product_cvrf_srpm = session.query(PRODUCT).filter(
                and_(
                    PRODUCT.productId == productId,
                    PRODUCT.packageName == srpm.sname
                )
            ).all()
            if len(product_cvrf_srpm):
                for cvrf_srpm in product_cvrf_srpm:
                    if srpm_version_compare(srpm.sourcerpm, cvrf_srpm.srcfilename, options.osv):
                        print(" * check ", srpm.sourcerpm)
                        print("   Higher version found :", cvrf_srpm.srcfilename)
        if options.osv and options.osv not in OSV_MAP:
            print(" warn : OSV %s is not in OSV_MAP" % options.osv)
        print("check done!")
    else:
        parser.print_help()
